#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include <math.h>
#include "lib_iic.h"
#include "bsp_lcd.h"
#include "esp_log.h"

static const char *TAG = "BSP_LCD";

static SemaphoreHandle_t xSemaphore = NULL;
static const uint8_t init1[4] = {0x80, 0x5a, 0x40, 0xa5};
static const uint8_t init2[38] = {0x80, 0xa8, 0x80, 0xae, 0x80, 0x66, 0XC0, 0x00, 0X80, 0xc4, 0x80, 0x84, 0x80,
								  0x36, 0xc0, 0x00, 0x80, 0x6d, 0xc0, 0x00, 0x80, 0x27, 0xc0, 0x01, 0x80, 0xab, 0x80,
								  0x5f, 0xc0, 0x0b, 0x80, 0xa2, 0xc0, 0x03, 0x80, 0x25, 0x00, 0xaf};
static const uint8_t init3[4] = {0x80, 0x25, 0x00, 0xaf};
static const uint8_t init4[2] = {0x80, 0x24};
static const uint8_t lcd_set_add[] = {0x80, 0X8A, 0XC0, 0X00, 0X80, 0XB1, 0XC0, 0X00, 0X80, 0X13, 0XC0, 0X00, 0X40, 0XDF};
static uint8_t buffer[29] = {0X20, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0x00, 0X00, 0X00,
							 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00,
							 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00};

static const uint8_t number_hex[10] = {0x7e, 0x06, 0x5b, 0x4f, 0x27, 0x6d, 0x7d, 0x46, 0x7f, 0x6f};
static const uint32_t dir_seg_hex[7] = {0X000375AD, 0X000375B8, 0X000375A6, 0X00037700, 0X000374C0, 0X0003E000, 0X00035800};
static const uint8_t speed_seg_pos[2][7] = {{25, 26, 28, 29, 30, 31, 27}, {41, 40, 38, 37, 36, 24, 39}};
static const uint8_t speed_limit_seg_pos[2][7] = {{58, 57, 47, 46, 45, 59, 44}, {54, 53, 50, 49, 48, 55, 56}};
static const uint8_t distance_seg_pos[4][7] = {{82, 81, 89, 88, 87, 83, 86}, {79, 78, 93, 92, 91, 80, 90}, {151, 150, 141, 140, 139, 152, 142}, {148, 147, 145, 144, 143, 149, 146}};
static const uint8_t gas_seg_pos[2][7] = {{196, 207, 200, 199, 198, 197, 208}, {210, 211, 215, 203, 202, 209, 214}};
static const uint8_t water_seg_pos[3][7] = {{194, 179, 177, 176, 175, 174, 178}, {193, 185, 183, 182, 181, 180, 184}, {192, 191, 189, 188, 187, 186, 190}};
static const uint8_t dir_seg_pos[18] = {162, 71, 70, 161, 160, 72, 74, 73, 159, 158, 75, 76, 77, 156, 155, 157, 154, 153};
static const uint8_t road_seg_pos[9][2] = {{61, 171}, {62, 170}, {63, 169}, {64, 168}, {65, 167}, {66, 166}, {67, 165}, {68, 163}, {69, 164}};
static const uint32_t road_seg_hex[8] = {0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};

void bsp_lcd_poweron(uint8_t on)
{
	if (on)
		I2C_Sendstr(init3, 4);
	else
		I2C_Sendstr(init4, 2);
}

void bsp_lcd_init(void)
{
	xSemaphore = xSemaphoreCreateMutex();
	I2C_GPIO_Init();
	I2C_Sendstr(init1, 4);
	vTaskDelay(10 / portTICK_PERIOD_MS);
	I2C_Sendstr(init2, 34);
	vTaskDelay(10 / portTICK_PERIOD_MS);
	bsp_lcd_alloff();
	I2C_Sendstr(init3, 4);
	vTaskDelay(10 / portTICK_PERIOD_MS);
	bsp_lcd_poweron(1);
}

void bsp_lcd_refresh(void)
{
	xSemaphoreTake(xSemaphore, portMAX_DELAY);
	// vTaskDelay(100 / portTICK_PERIOD_MS);
	// esp_log_buffer_hex(TAG, buffer, 29);
	I2C_Sendstr(lcd_set_add, 14);
	I2C_Sendstr(buffer, 29);
	xSemaphoreGive(xSemaphore);
}

void bsp_lcd_allon(void)
{
	for (uint8_t i = 1; i < 28; i++)
	{
		buffer[i] = 0xff;
	}
	bsp_lcd_refresh();
}

void bsp_lcd_alloff(void)
{
	for (uint8_t i = 1; i < 28; i++)
	{
		buffer[i] = 0x00;
	}
	bsp_lcd_refresh();
}

void bsp_display_segment(uint8_t area_num, uint8_t on)
{
	buffer[area_num / 8 + 1] &= ~(1 << (7 - (area_num % 8)));
	if (on)
	{
		buffer[area_num / 8 + 1] |= (1 << (7 - (area_num % 8)));
	}
	// ESP_LOGI(TAG, "index:%d  value:0x%x", area_num / 8 + 1, buffer[area_num / 8 + 1]);
}

static void bsp_display_number(const uint8_t *area, uint8_t num, uint8_t on)
{
	uint8_t temp = number_hex[num];
	// ESP_LOGI(TAG, "temp : 0x%x    num : %d", temp, num);
	for (uint8_t i = 0; i < 7; i++)
	{
		bsp_display_segment(area[i], (temp & 0x40) && on);
		temp = temp << 1;
	}
}

void bsp_display_speed(uint8_t speed, uint8_t on)
{
	speed = (speed > 199) ? 199 : speed;
	bsp_display_number(speed_seg_pos[0], speed % 10, on);
	bsp_display_number(speed_seg_pos[1], 0, 0);
	if (speed > 9)
	{
		bsp_display_number(speed_seg_pos[1], speed / 10 % 10, on);
	}
	if (speed > 99 && on)
		bsp_display_segment(SPEED_ONE, 1);
	else
		bsp_display_segment(SPEED_ONE, 0);
}

void bsp_display_speed_limit(uint8_t speed, uint8_t on)
{
	speed = (speed > 199) ? 199 : speed;
	bsp_display_number(speed_limit_seg_pos[0], speed % 10, on);
	bsp_display_number(speed_limit_seg_pos[1], 0, 0);
	if (speed > 9)
	{
		bsp_display_number(speed_limit_seg_pos[1], speed / 10 % 10, on);
	}
	if (speed > 99 && on)
		bsp_display_segment(SPEED_LIMIT_ONE, 1);
	else
		bsp_display_segment(SPEED_LIMIT_ONE, 0);
}

void bsp_display_distance(uint16_t distance, uint8_t on)
{
	distance = (distance > 9999) ? 9999 : distance;

	bsp_display_number(distance_seg_pos[0], distance % 10, on);
	bsp_display_number(distance_seg_pos[1], 0, 0);
	bsp_display_number(distance_seg_pos[2], 0, 0);
	bsp_display_number(distance_seg_pos[3], 0, 0);

	if (distance > 9)
	{
		bsp_display_number(distance_seg_pos[1], distance / 10 % 10, on);
	}

	if (distance > 99)
	{
		bsp_display_number(distance_seg_pos[2], distance / 100 % 10, on);
	}

	if (distance > 999)
	{
		bsp_display_number(distance_seg_pos[3], distance / 1000 % 10, on);
	}
}

void bsp_display_gas(uint8_t gas, uint8_t on)
{
	gas = (gas > 199) ? 199 : gas;

	bsp_display_number(gas_seg_pos[0], gas % 10, on);
	bsp_display_number(gas_seg_pos[1], 0, 0);
	if (gas > 9)
	{
		bsp_display_number(gas_seg_pos[1], gas / 10 % 10, on);
	}
	if (gas > 99 && on)
		bsp_display_segment(GAS_ONE, 1);
	else
		bsp_display_segment(GAS_ONE, 0);
}

void bsp_display_water(int16_t temp, uint8_t on)
{
	//高位清零
	temp = (temp > 999) ? 999 : (temp < -99) ? -99
											 : temp;

	bsp_display_number(water_seg_pos[1], 0, 0);
	bsp_display_number(water_seg_pos[2], 0, 0);

	if (temp < 0)
	{
		bsp_display_segment(190, 1); //开启负号
		bsp_display_number(water_seg_pos[0], abs(temp) % 10, on);
		if (temp < -9)
		{
			bsp_display_number(water_seg_pos[1], abs(temp) / 10 % 10, on);
		}
	}
	else
	{
		bsp_display_segment(190, 0); //关闭负号
		bsp_display_number(water_seg_pos[0], temp % 10, on);

		if (temp > 9)
		{
			bsp_display_number(water_seg_pos[1], temp / 10 % 10, on);
		}
		if (temp > 99)
		{
			bsp_display_number(water_seg_pos[2], temp / 100 % 10, on);
		}
	}
}

void bsp_display_road(uint8_t speed, uint8_t num, uint8_t on)
{
	static uint8_t count;
	static uint32_t bit_mask;
	static uint8_t current_index = 100;

	if (current_index != num)
	{
		count = 0;
		current_index = num;
		bit_mask = road_seg_hex[current_index];
	}

	if (count >= speed)
	{
		count = 0;
		uint32_t temp = bit_mask;
		for (uint8_t i = 0; i < 9; i++)
		{
			bsp_display_segment(road_seg_pos[i][0], (temp & 0x01) && on);
			bsp_display_segment(road_seg_pos[i][1], (temp & 0x01) && on);
			temp = temp >> 1;
		}
		bit_mask = ((bit_mask >> (9 - 1)) & 0x1ff) | ((bit_mask << 1) & 0x1ff); //循环左移
	}

	count++;
}

void bsp_display_dir(uint8_t dir, uint8_t on)
{
	uint32_t temp = dir_seg_hex[dir];
	for (uint8_t i = 0; i < 18; i++)
	{
		bsp_display_segment(dir_seg_pos[i], (temp & 0x01) && on);
		temp = temp >> 1;
	}
}
